package cn.com.self.apis.file.service.impl;

import cn.com.self.apis.file.entity.Files;
import cn.com.self.apis.file.service.intf.IFileService;
import cn.com.self.apis.file.util.DateUtils;
import cn.com.selfsoft.smartcity.core.service.BaseServiceImpl;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class FileServiceImpl extends BaseServiceImpl<Files, String> implements IFileService {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

    @Value("${file.attachRootPath}")
    private String attachRootPath;

    @Value("${file.url}")
    public String fileUrl;

    @Autowired
    private IFileService fileService;

    @Override
    public Map<String, Object> uploadByUrl(String urlPath, String path, String fileType) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        //new一个URL对象
        URL url = new URL(urlPath);
        //打开链接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求方式为"GET"
        conn.setRequestMethod("GET");
        //超时响应时间为5秒
        conn.setConnectTimeout(5 * 1000);
        //通过输入流获取图片数据
        InputStream inStream = conn.getInputStream();
        //文件大小
        int fileSize = inStream.available();
        if (fileSize > (5 * 1024 * 1024)) {
            result.put("code", "401");
            result.put("errmsg", "图片超过5MB");
            return result; //超过1MB
        }
        //得到图片的二进制数据，以二进制封装得到数据，具有通用性
        byte[] data = readInputStream(inStream);
        //创建本地文件
        String fileName = DigestUtils.md5Hex(UUID.randomUUID().toString() + System.currentTimeMillis());// 由uuid加时间戳 通过md5转码后作为文件名
        fileName = fileName + "." + (StringUtils.isBlank(fileType) ? "jpg" : fileType);
        String filePath = "/" + sdf.format(new Date()) + "/" + fileName;
        if (!createFile(path + filePath)) {
            throw new IOException("创建文件失败");
        }
        File imageFile = new File(path + filePath);
        //创建输出流
        FileOutputStream outStream = new FileOutputStream(imageFile);
        //写入数据
        outStream.write(data);
        //关闭输出流
        outStream.close();

        result.put("code", "200");
        result.put("errmsg", "SUCCESS");
        result.put("fileName", fileName);
        result.put("filePath", filePath);
        result.put("fileSize", fileSize);
        return result;
    }

    private synchronized boolean createFile(String destFileName) {
        File file = new File(destFileName);
        if (file.exists()) {//失败，目标文件已存在！
            return false;
        }
        if (destFileName.endsWith(File.separator)) {//失败，目标文件不能为目录！
            return false;
        }
        //判断目标文件所在的目录是否存在
        if (!file.getParentFile().exists()) {
            //如果目标文件所在的目录不存在，则创建父目录
            //目标文件所在目录不存在，准备创建它！
            if (!file.getParentFile().mkdirs()) {//创建目标文件所在目录失败！
                return false;
            }
        }
        //创建目标文件
        try {
            if (file.createNewFile()) {//成功！
                return true;
            } else { //失败！
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    private byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //创建一个Buffer字符串
        byte[] buffer = new byte[1024];
        //每次读取的字符串长度，如果为-1，代表全部读取完毕
        int len = 0;
        //使用一个输入流从buffer里把数据读取出来
        while ((len = inStream.read(buffer)) != -1) {
            //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
            outStream.write(buffer, 0, len);
        }
        //关闭输入流
        inStream.close();
        //把outStream里的数据写入内存
        return outStream.toByteArray();
    }

    @Override
    public void download(HttpServletResponse response, String filePath, String fileType, String fileName) throws IOException {

//        response.setCharacterEncoding("UTF-8");
//        response.setContentType("UTF-8");

        File file = new File(filePath);
        long fileLength = file.length();

        if (fileType.equals("txt")) {
            response.setContentType("text/plain;");
            response.setHeader("Content-disposition", "attachment; filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1"));

        } else if (fileType.equals("doc")) {
            response.setContentType("application/msword;");
            response.setHeader("Content-disposition", "attachment; filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1"));

        } else if (fileType.equals("xls")) {
            response.setContentType("application/ms-excel;");
            response.setHeader("Content-disposition", "attachment; filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1"));

        } else if (fileType.equals("pdf")) {
            response.setContentType("application/pdf;");
            response.setHeader("Content-disposition", "attachment; filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1"));

        } else if (fileType.equals("jpg") || fileType.equals("jpeg") || fileType.equals("png")) {
            response.setContentType("image/jpeg");
            response.setHeader("Content-Length", "" + fileLength);
        } else if (fileType.equals("amr")) {
            response.setContentType("audio/amr-wb");
            response.setHeader("Content-disposition", "attachment; filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1"));

        } else {
            response.setContentType("application/x-msdownload;");
            response.setHeader("Content-disposition", "attachment; filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1"));

        }

        InputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            bis = new BufferedInputStream(new FileInputStream(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        // response.setHeader("Content-Length", "" + fileLength);
        bos = new BufferedOutputStream(response.getOutputStream());
        byte[] buff = new byte[2048];
        int bytesRead;
        while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
            bos.write(buff, 0, bytesRead);
        }

        if (bis != null) {
            bis.close();
        }
        if (bos != null) {
            bos.flush();
            bos.close();
        }

    }

    @Override
    public void saveFile(Map<String, String> map) {
        Files files = new Files();
        files.setFilename(map.get("filename"));
        files.setFilename2(map.get("filename2"));
        files.setFilepath(map.get("filePath"));
        files.setFilesize(map.get("filesize"));
        files.setSuffix(map.get("suffix"));
        files.setFiletype(map.get("filetype"));
        files.setCreateDate(new Date());
        files.setUpdateDate(new Date());
        files = this.create(files);
        map.put("fileId", files.getId() + "");
    }

    @Override
    public List<Files> findAllFiles() {
        return fileService.findAllFiles();
    }

    @Override
    public Files upload(HttpServletRequest request) {
        Files files = new Files();
        try {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
            Object[] fileKeys = fileMap.keySet().toArray();
            MultipartFile multipartFile = fileMap.get(fileKeys[0]);
            //文件大小，字节,90.2 KB (92,422 字节)
            long size = multipartFile.getSize();
            String filesize;
            double size2;
            if (size / (1024 * 1024 * 1024) > 1) {
                //单位G
                size2 = new BigDecimal((float) size / (1024 * 1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                filesize = size2 + "G";
            } else if (size / (1024 * 1024) > 1) {
                //单位M
                size2 = new BigDecimal((float) size / (1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                filesize = size2 + "M";
            } else {
                //单位KB
                size2 = new BigDecimal((float) size / (1024)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                filesize = size2 + "KB";
            }
            String timeUrl = DateUtils.getYear() + DateUtils.getMonth() + DateUtils.getDay();
            //文件名
            String filename = multipartFile.getOriginalFilename();
            String[] name = filename.split("\\.");
            //文件扩展名
            String suffix = name[name.length - 1];
            //文件类型
            String filetype = request.getParameter("filetype");
            String filename2 = System.currentTimeMillis() + "_" + new Random().nextInt(9999) + "." + name[name.length - 1];
            String filePath = attachRootPath + '/' + timeUrl + '/';
            File newFile = new File(filePath, filename2);
            //判断路径是否存在，如果不存在就创建一个
            if (!newFile.getParentFile().exists()) {
                newFile.getParentFile().mkdirs();
            }
            multipartFile.transferTo(newFile);
            //保留文件本地路径
            String filepath = "/download/" + timeUrl + '/' + filename2;
            files.setFilesize(filesize);
            files.setFilepath(filepath);
            files.setFilename(filename);
            files.setFilename2(filename2);
            files.setSuffix(suffix);
            files.setFiletype(filetype == null ? "0" : filetype);
            files.setCreateDate(new Date());
            files.setUpdateDate(new Date());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileService.create(files);
    }

    @Override
    public List<Files> uploads(HttpServletRequest request) {
        List<Files> filesList = new ArrayList<>();
        //从HttpServletRequest 获取文件List
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        List<MultipartFile> multipartFileList = multipartRequest.getFiles("files");
        for (MultipartFile multipartFile : multipartFileList) {
            Files files = new Files();
            //文件大小，字节,90.2 KB (92,422 字节)
            long size = multipartFile.getSize();
            String filesize;
            double size2;
            if (size / (1024 * 1024 * 1024) > 1) {
                //单位G
                size2 = new BigDecimal((float) size / (1024 * 1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                filesize = size2 + "G";
            } else if (size / (1024 * 1024) > 1) {
                //单位M
                size2 = new BigDecimal((float) size / (1024 * 1024)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                filesize = size2 + "M";
            } else {
                //单位KB
                size2 = new BigDecimal((float) size / (1024)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                filesize = size2 + "KB";
            }
            String timeUrl = DateUtils.getYear() + DateUtils.getMonth() + DateUtils.getDay();
            //文件名
            String filename = multipartFile.getOriginalFilename();
            String[] name = filename.split("\\.");
            //文件扩展名
            String suffix = name[name.length - 1];
            //文件类型
            String filetype = request.getParameter("filetype");
            String filename2 = System.currentTimeMillis() + "_" + new Random().nextInt(9999) + "." + name[name.length - 1];
            String filePath = attachRootPath + '/' + timeUrl + '/';
            File newFile = new File(filePath, filename2);
            //判断路径是否存在，如果不存在就创建一个
            if (!newFile.getParentFile().exists()) {
                newFile.getParentFile().mkdirs();
            }
            try {
                multipartFile.transferTo(newFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //保留文件本地路径
            String filepath = "/download/" + timeUrl + '/' + filename2;
            files.setFilesize(filesize);
            files.setFilepath(filepath);
            files.setFilename(filename);
            files.setFilename2(filename2);
            files.setSuffix(suffix);
            files.setFiletype(filetype == null ? "0" : filetype);
            files.setCreateDate(new Date());
            files.setUpdateDate(new Date());
            fileService.create(files);
            filesList.add(files);
        }
        return filesList;
    }

}
